/*
  Tên:Nguyễn Văn Huy
  MSSV:11374891
  Lớp:DHTH7DLT
  Ngày hoàn thành:28/04/2012
  */
#include "tasksmodel.h"
#include <QtGui>

TasksModel::TasksModel(QObject *parent): QAbstractItemModel(parent)
{
    nrOfColumns = 2;
    //QString str="Bạn có chắc chắn muốn thoát";
    headerNames<<QString::fromUtf8("Danh mục sách                ")<<QString::fromUtf8("Tên Sách");
        topQueryReady = false;
        topRowsFetched = 0;
        topRowsCount = 0;
        selectedId = 0;
        DBC=new MySqlConnection();
        DBC->Open();
        //QSqlQuery select(DBC->DB);
        //select.prepare("SELECT * FROM Sach");
          //      select.exec();
          //  while (select.next())
           // {
              //  qDebug() << select.value(0).toString();
            //}
}
QVariant TasksModel::data ( const QModelIndex & index, int role ) const
{
    if (!index.isValid()) return QVariant();
    int column = index.column();

    if (role == Qt::UserRole)
    {
        QSqlQuery* query = verifyAndPrepareQuery(index.parent());
        //query->exec();
        if (!query->seek(index.row()))
            return QVariant("x");
        return query->value(0);
    }
    else if (role == Qt::DisplayRole || role == Qt::EditRole)
    {
        QSqlQuery* query = verifyAndPrepareQuery(index.parent());
        //query->exec();
        if (!query->seek(index.row()))
            return QVariant("x");
        switch (column)
        {
            case 0: return query->value(2).toString();
            case 1: return query->value(4).toString() +"";
        }
    }
    else if (role == Qt::CheckStateRole) {
        // set status of checkbox in 2nd column
        if (column == 1) {

            QSqlQuery* query = verifyAndPrepareQuery(index);
            //query->exec();
           // qDebug()<<query->value(0).toString();
            if (!query->seek(index.row())) return QVariant();

            if (query->value(3).toInt() > 0)
                return Qt::Checked;
            else
               return Qt::Unchecked;
        }
    }
    else if (role == Qt::TextAlignmentRole) {
        switch (column)
        {
            case 0: return Qt::AlignLeft + Qt::AlignVCenter;
            case 1: return Qt::AlignRight + Qt::AlignVCenter;
        }
    }

    return QVariant();

}
Qt::ItemFlags TasksModel::flags ( const QModelIndex & index ) const
{
    if (!index.isValid()) return 0;

    Qt::ItemFlags result = Qt::ItemIsEnabled | Qt::ItemIsSelectable;

    if (index.column()==0) {
        result |= Qt::ItemIsEditable;
    }
    else if (index.column()==1) {
        result |= Qt::ItemIsUserCheckable;
    }

    return result;
}

QVariant TasksModel::headerData ( int section, Qt::Orientation orientation, int role) const
{
    //return QVariant();
    if (role != Qt::DisplayRole)
                    return QVariant();
            if (orientation == Qt::Horizontal)
                    return headerNames.at(section);
}

int TasksModel::columnCount ( const QModelIndex & parent ) const
{
    return nrOfColumns;
}


int TasksModel::rowCount (const QModelIndex & parent) const
{
    if (parent.isValid() && parent.column() != 0)
        return 0;

    int id;
    if (parent.isValid())
        id = parent.internalId();
    else
        id = 0;

    return totalCount(id);
}


bool TasksModel::hasChildren ( const QModelIndex & parent) const
{
    if (parent.isValid()) {
        if (totalCount(parent.internalId()) > 0)
            return true;
    } else {
        if (totalCount(0) > 0)
            return true;
    }

    return false;
}

void TasksModel::sort ( int column, Qt::SortOrder order )
{
    //???
}

// TreeView methods
QModelIndex TasksModel::index ( int row, int column, const QModelIndex& parent ) const
{
    qDebug() << "index " << row << " " << column;

    if (row < 0 || column < 0 || column >= nrOfColumns)
            // || (parent.isValid() && parent.column() != 0))
        return QModelIndex();

    if (!hasIndex(row, column, parent))
        return QModelIndex();
    //DBC->Open();
    QSqlQuery* query = verifyAndPrepareQuery(parent);

    if (!query->seek(row)) return QModelIndex();
    int id = query->value(0).toInt();

    if (!nodeParams.contains(id))
    {
        NodeParams params;
        params.parentId = (int)query->value(1).toInt();
        params.row = row;
        nodeParams.insert(id, params);

    }

    qDebug() << "create index row" << row << " column " << column << " id " << id;

    return QAbstractItemModel::createIndex(row, column, id);
}

QModelIndex TasksModel::parent ( const QModelIndex & index ) const
{
    //return QModelIndex();

    if (!index.isValid()) { return QModelIndex(); }
    if (!nodeParams.contains(index.internalId())) { qDebug("b"); return QModelIndex();}

    NodeParams itemParams = nodeParams.value(index.internalId());

    if (itemParams.parentId == 0) return QModelIndex();
    if (!nodeParams.contains(itemParams.parentId)) { qDebug("d"); return QModelIndex(); }

    NodeParams parentParams = nodeParams.value(itemParams.parentId);

    int parentId = itemParams.parentId;
    int parentRow = parentParams.row;

    return QAbstractItemModel::createIndex(parentRow, 0, parentId);

}

// Edit methods
bool TasksModel::setData ( const QModelIndex & index, const QVariant & value, int role )
{
    return false;
}

bool TasksModel::setHeaderData ( int section, Qt::Orientation orientation, const QVariant & value, int role )
{
    return true;
    ///QStringList headers;
    //headers << tr("Title") << tr("Description");
   // QVector<QVariant> rootData;
    //return QVariant();
}

// Build and return query object for current index parent
QSqlQuery* TasksModel::verifyAndPrepareQuery (const QModelIndex& index) const
{
    DBC->Open();

    if (!index.isValid())
    {
        // prepare query for root
        if (!topQueryReady)
        {

            QString sql = "SELECT MaSach,MaTheLoai,TenTheLoai FROM Sach WHERE MaTheLoai =0";
            topQuery = QSqlQuery(DBC->DB);
            topQuery.prepare(sql);
            topQuery.exec();
            topRowsFetched = 0;
            topRowsCount = 0;
            topQueryReady = true;
        }
        return &topQuery;

    }
    else
    {
        // prepare queries for subitems (queries stored in subQueries QMap)
        qint64 id = index.internalId();
        if (!subQueries.contains(id))
        {

            QString sql = "SELECT MaSach,MaTheLoai,TenSach FROM Sach WHERE MaTheLoai =" + QString::number(id);
            QSqlQuery* querySub = new QSqlQuery(DBC->DB);
            querySub->prepare(sql);
            querySub->exec();
            subQueries.insert(id, querySub);
            //rowsFetched.insert(id, 0);
            return querySub;
        }
        return subQueries.value(id);
    }

}

int TasksModel::totalCount(const qint64 id, bool force) const
{
    DBC->Open();
    force = true; // temporary setting, to force recalculation in each request, to be optimized
    if (id > 0) {
        if (!rowsCount.contains(id) || force) {

            QString sql = "SELECT COUNT(*) FROM Sach WHERE MaTheLoai = "+ QString::number(id);
            QSqlQuery countQuery(DBC->DB);
            countQuery.prepare(sql);
            countQuery.exec();
            countQuery.next();
            int count = countQuery.value(0).toInt();

            rowsCount[id] = count;
            return count;
        }
        return rowsCount.value(id);
    } else {
        if (topRowsCount == 0 || force) {

            QString sql = "SELECT COUNT(*) FROM Sach WHERE MaTheLoai = 0 ";
            QSqlQuery countQuery(DBC->DB);
            countQuery.prepare(sql);
            countQuery.exec();
            countQuery.next();
            topRowsCount = countQuery.value(0).toInt();
        }

        return topRowsCount;
    }
}

void TasksModel::recountTotalCount(const qint64 id) const
{
    // reset variables related to rowsCount and data functions. Called after new child is created or removed
    if (id > 0) {
        rowsCount.remove(id);
        subQueries.remove(id);
    }
    else {
        topRowsCount = 0;
        topQueryReady = false;
    }
    totalCount(id);
}

QModelIndex TasksModel::indexForId(int id)
{
    // convert id to index based on data stored in nodeParams
    if (id == 0) return QModelIndex();
    if (!nodeParams.contains(id)) { qDebug() << "z"; return QModelIndex(); }

    NodeParams params = nodeParams.value(id);
    return QAbstractItemModel::createIndex(params.row, 0, id);
}

